/*
 *	
 *	- results tab
 *	- trace tab
 *	- status: errors, warnings and info
 *	- progress bar
 *	- threads
 */

package text.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import text.util.DBConnector;
import text.ia.InputAnalyzer;
import text.translation.Translator;

public class TranslationModeViewer extends Viewer implements ActionListener {

	private JFileChooser fc = null;
	private JTabbedPane tabbedPane = null;
	private JTextArea sourceTextArea = null;
	private JTextArea translatedTextArea = null;
	private JComboBox sourceCombo = null;
	private JComboBox targetCombo = null;
	private String sourcePath = null;
	private String targetPath = null;
	private JTabbedPane resultTab = null;
//	private JTabbedPane traceTab = null;
	private char tabMode = '\0';
	private Vector vOrigSentences = null;
	private Vector vTranslatedSentences = null;
	private JPanel traceTab = null;
	private JTree translateTree = null;
	
	public void setEnabled(boolean bEnabled) {
		if(sourceTextArea != null) {
			sourceTextArea.setEnabled(bEnabled);
		}

		if(translatedTextArea != null) {
			translatedTextArea.setEnabled(bEnabled);
		}

		if(sourceCombo != null) {
			sourceCombo.setEnabled(bEnabled);
		}

		if(targetCombo != null) {
			targetCombo.setEnabled(bEnabled);
		}
	}
	
	/**
	 * main method allows us to run as a standalone demo.
	 */
	public static void main(String[] args) {
		TranslationModeViewer translationModeViewer = new TranslationModeViewer();
		translationModeViewer.init();
	}
	
	/**
	 * TranslationModeViewer Constructor
	 */
	public TranslationModeViewer() {
		// Set the title for this demo, and an icon used to represent this
		// demo inside the GUI app.
		super(null, "TranslationModeViewer", "translationMode.GIF");

		createTranslationModeUI();
	}
	
	public void createTranslationModeUI() {
		tabbedPane = createTabbedPane();
		tabbedPane.setBorder(null);
		tabbedPane.addChangeListener(new TabAction(this));

		//Translation Mode Tab
		tabbedPane.addTab("Translation Mode", createSourcePanel());
		
		getViewerPanel().add(tabbedPane, BorderLayout.CENTER);
	}

	private JTabbedPane createTabbedPane() {
		return new JTabbedPane(JTabbedPane.TOP) {
			protected void paintComponent(Graphics g) {
				Color orig = g.getColor();
				Rectangle tabBounds = getBoundsAt(0);
				int tabLowerY = tabBounds.y + tabBounds.height;

				g.setColor(new Color(247, 243, 233));
				g.fillRect(0, 0, getWidth(), tabLowerY);

				g.setColor(orig);
				super.paintComponent(g);

				g.setColor(Color.WHITE);
				g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
				g.drawRect(1, tabLowerY - 1, getWidth() - 3, getHeight() - tabLowerY - 1);
				g.setColor(orig);
			}
		};
	}

	public JPanel createSourcePanel() {
		JPanel sourcePanel = new JPanel(new BorderLayout());
		sourcePanel.setBorder(new TitledBorder("Source Text"));

		JPanel sourceTextPanel = new JPanel(new BorderLayout());
		sourcePanel.add(sourceTextPanel, BorderLayout.CENTER);
		
		JPanel sourceComboPanel = new JPanel();
		sourceTextPanel.add(sourceComboPanel, BorderLayout.NORTH);

		sourceComboPanel.setPreferredSize(new Dimension(184, 36));

		JLabel sourceLabel = new JLabel();
		sourceComboPanel.add(sourceLabel);
		sourceLabel.setText("Source Language");

		ComboBoxModel sourceComboModel = new DefaultComboBoxModel(
			new String[] { "English", "Filipino" });
		
		sourceCombo = new JComboBox();
		sourceComboPanel.add(sourceCombo);
		sourceCombo.setModel(sourceComboModel);
		sourceCombo.addActionListener(this);

		JLabel blankLabel = new JLabel();
		sourceComboPanel.add(blankLabel);
		blankLabel.setText("                         ");

		JLabel targetLabel = new JLabel();
		sourceComboPanel.add(targetLabel);
		targetLabel.setText("Target Language");

		ComboBoxModel targetComboModel = new DefaultComboBoxModel(
			new String[] { "Filipino", "English" });
		
		targetCombo = new JComboBox();
		sourceComboPanel.add(targetCombo);
		targetCombo.setModel(targetComboModel);
		targetCombo.addActionListener(this);

		JScrollPane sourceScrollPane = new JScrollPane();
		sourceTextPanel.add(sourceScrollPane, BorderLayout.CENTER);

		sourceTextArea = new JTextArea();
		sourceTextArea.setLineWrap(true);
		sourceTextArea.setWrapStyleWord(true);
		sourceTextArea.setFont(new Font("Courier", Font.PLAIN, 12));
		sourceTextArea.setBorder(new TitledBorder("Source: Untitled"));
		sourceTextArea.getDocument().addDocumentListener(new ChangeAction(sourceTextArea));

		sourceScrollPane.setViewportView(sourceTextArea);
						
		return sourcePanel;	
	}
	
	public void actionPerformed(ActionEvent ae){
		Object source = ae.getSource();
		
		if(source == sourceCombo){
			if(sourceCombo.getSelectedIndex() == 0) {
				targetCombo.setSelectedIndex(0);
			}else {
				targetCombo.setSelectedIndex(1);
			}
		}
		if(source == targetCombo){
			if(targetCombo.getSelectedIndex() == 0) {
				sourceCombo.setSelectedIndex(0);
			}else {
				sourceCombo.setSelectedIndex(1);
			}
		}
	}

	public void newAction(JTextArea tArea){
		if(tabMode == 'S') {
			//clear text area
			sourceTextArea.setText("");
			//clear stored path
			sourcePath = null;
			//title
			tArea.setBorder(new TitledBorder("Untitled"));
		}
	}

	public void openAction(JTextArea tArea){
		if(tabMode == 'S') {
			fc = new JFileChooser();
			fc.setCurrentDirectory(new File("./resources/files/") );  
			TExtFileFilter filter = new TExtFileFilter();
			filter.addExtension("txt");
			fc.setFileFilter(filter);
			int returnVal = fc.showOpenDialog(getViewerPanel());
			
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File f = fc.getSelectedFile();
				BufferedReader bf = null;
				if (filter.accept(f)){
					try{
						bf = new BufferedReader(new FileReader(f) );
						tArea.setText("");
						String line;
						while ( (line = bf.readLine() )!= null){
							tArea.append(line +"\n");
						}
					   	bf.close();
						sourcePath = f.getPath();
						tArea.setBorder(new TitledBorder(f.getName()));
					}catch(FileNotFoundException fnfe){
					}catch(IOException ioe){
					}catch(Exception ex){
					}
				}else{
					System.out.println("File not accepted.");
				}
			} 
		}
	}

	public void saveAction(JTextArea tArea, String strType) {
		File f = null;
		if(strType.charAt(0) == 'S' && sourcePath != null) {
			f = new File(sourcePath);
			if(f.exists()) {
				saveFile(tArea, strType, f, strType+"Save");
			}else {
				saveFile(tArea, strType, null, strType+"Save");
			}
		}else if(targetPath != null) {
			f = new File(targetPath);
			if(f.exists()) {
				saveFile(tArea, strType, f, strType+"Save");
			}else {
				saveFile(tArea, strType, null, strType+"Save");
			}
		}else {
			saveFile(tArea, strType, null, strType+"Save");
		}
	}
	
	public void saveAsAction(JTextArea tArea, String strType) {
		saveFile(tArea, strType, null, strType+"Save As");
	}

	private void saveFile(JTextArea tArea, String strType, File file, String strTitle) {
		TExtFileFilter filter = new TExtFileFilter();
		filter.addExtension("txt");
		if(file == null) {
			//create or choose a file
			fc = new JFileChooser();
			fc.setCurrentDirectory(new File("./resources/files/") );  
			fc.setFileFilter(filter);
			fc.setDialogTitle(strTitle);
			int returnVal = fc.showSaveDialog(getViewerPanel());
			
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File f = fc.getSelectedFile();
				if(f.exists()) {
					int selectedIndex = JOptionPane.showConfirmDialog(getViewerPanel(), "The file, "+f.getName()+", already exists.\nDo you want to overwrite this file?", strTitle, JOptionPane.YES_NO_OPTION);
					//YES
					if(selectedIndex == 0) {
						createFile(tArea, strType, filter, f);
					}
				}else {
					createFile(tArea, strType, filter, f);
				}
		  	}
		}else {
			//overwrite the existing file
			createFile(tArea, strType, filter, file);
		}
	}

	private void createFile(JTextArea tArea, String strType, TExtFileFilter filter, File f) {
		if(!filter.accept(f)) {
			f = filter.appendExtension(f, ".txt");
		}
		if (filter.accept(f)) {
			try{
	            FileWriter fw = new FileWriter(f);
	            fw.write(tArea.getText() );
	            fw.close();
	            if(strType.charAt(0) == 'S') {
		            sourcePath = f.getPath();
	            }else {
		            targetPath = f.getPath();
	            }
				tArea.setBorder(new TitledBorder(strType + f.getName()));
			}catch(FileNotFoundException fnfe) {
			}catch(IOException ioe) {
			}catch(Exception ex) {
			}
		}else{
			System.out.println("File not accepted.");
		}
	}

	//cut
	public void cutAction(JTextArea tArea) {
		tArea.cut();
	}
	
	//copy
	public void copyAction(JTextArea tArea) {
		tArea.copy();
	}
	
	//paste
	public void pasteAction(JTextArea tArea) {
		tArea.paste();
	}
	
	//translate
	public void translateAction() {
		DBConnector.connect();
		String result = startTranslation();

		if(tabbedPane.indexOfTab("Trace") != -1) {
			traceAction();
		}

		if(result != null) {
			resultAction(result);
		}else {
			JOptionPane.showMessageDialog(null, "There are no sentences to be"
				+ " translated.", null, JOptionPane.WARNING_MESSAGE);
		}
		
		DBConnector.close();
	}

	//result
	public void resultAction(String result) {
		if(resultTab == null) {
			resultTab = new JTabbedPane(JTabbedPane.TOP);
			resultTab.addTab("Translated Text", createTranslatedText(result));
			resultTab.addTab("Tabular Representation", createResultsTable());
	
			tabbedPane.addTab("Results", resultTab);
		}else {
			resultTab.removeTabAt(0);
			resultTab.removeTabAt(0);
			resultTab.addTab("Translated Text", createTranslatedText(result));
			resultTab.addTab("Tabular Representation", createResultsTable());
		}		
		tabbedPane.setSelectedComponent(resultTab);
	}

	private JPanel createResultsTable() {
		JPanel extractedTemplatesTab = new JPanel(new BorderLayout());
		JPanel language = new JPanel(new BorderLayout());
		JScrollPane extractedTemplatesScrollPane = new JScrollPane();
		extractedTemplatesTab.add(language, BorderLayout.NORTH);
		
		JLabel spaceLabel = new JLabel();
		JLabel space2Label = new JLabel();
		JLabel sourceLabel = new JLabel();
		JLabel targetLabel = new JLabel();
		language.add(spaceLabel, BorderLayout.NORTH);
		language.add(sourceLabel, BorderLayout.WEST);
		language.add(targetLabel, BorderLayout.EAST);
		language.add(space2Label, BorderLayout.SOUTH);
		spaceLabel.setText(" ");
		space2Label.setText(" ");
		sourceLabel.setText("Source Language: " + sourceCombo.getSelectedItem());
		targetLabel.setText("Target Language: " + targetCombo.getSelectedItem());
		
		extractedTemplatesTab.add(extractedTemplatesScrollPane, BorderLayout.CENTER);

		Vector vColumnNames = new Vector();
		vColumnNames.add("Sentence #");
		vColumnNames.add("Original Sentence");
		vColumnNames.add("Translation");

		Vector vRow = null;
		Vector vData = new Vector();

		if(vOrigSentences != null && vTranslatedSentences != null) {
			for(int i = 0; i < vOrigSentences.size(); i++) {
				vRow = new Vector();
				vRow.add(String.valueOf(i+1));
				vRow.add(vOrigSentences.get(i));
				vRow.add(vTranslatedSentences.get(i));
				vData.add(vRow);
			}
		}

		TableModel resultsTableModel = new DefaultTableModel(vData, vColumnNames){
			public Class getColumnClass(int c) {
            	//hard coded: second col is an INTEGER for correct sorting of ID's
            	Class cClass = null;
            	
            	if(c == 0) {
            		try {
            			cClass = Class.forName("java.lang.Integer");
            		}catch(ClassNotFoundException e) {
            			e.printStackTrace();
            		}
            	}else {
            		cClass = getValueAt(0, c).getClass();
            	}
            	
            	return cClass;
            }
		};
		
        TableSorter sorter = new TableSorter(resultsTableModel);
		JTable resultsTable = new JTable(sorter);
        sorter.setTableHeader(resultsTable.getTableHeader());
		resultsTable.getTableHeader().setReorderingAllowed(false);
		resultsTable.setDragEnabled(true);
		extractedTemplatesScrollPane.setViewportView(resultsTable);
		
		return extractedTemplatesTab;
	}

	private JPanel createTranslatedText(String result) {
		JPanel translatedPanel = new JPanel(new BorderLayout());

		JScrollPane translatedScrollPane = new JScrollPane();
		translatedPanel.add(translatedScrollPane, BorderLayout.CENTER);

		translatedTextArea = new JTextArea();
		translatedTextArea.setLineWrap(true);
		translatedTextArea.setWrapStyleWord(true);
		translatedTextArea.setFont(new Font("Courier", Font.PLAIN, 12));
		translatedTextArea.setBorder(new TitledBorder("Translation: Untitled"));
		translatedTextArea.getDocument().addDocumentListener(new ChangeAction(translatedTextArea));

		translatedScrollPane.setViewportView(translatedTextArea);

		//SET THE TRANSLATION
		setTranslatedText(result);
								
		return translatedPanel;	
	}

	//trace
	public void traceAction() {
		if(tabbedPane.indexOfTab("Trace") != -1) {
			tabbedPane.remove(tabbedPane.indexOfTab("Trace"));
		}

		traceTab = createTree(translateTree);
		tabbedPane.addTab("Trace", traceTab);
	
		tabbedPane.setSelectedComponent(traceTab);
	}

	private JPanel createTree(JTree tree) {
		JPanel candidateTemplatesTab = new JPanel(new BorderLayout());
		JPanel language = new JPanel(new BorderLayout());
		candidateTemplatesTab.add(language, BorderLayout.NORTH);
		
		JLabel spaceLabel = new JLabel();
		JLabel space2Label = new JLabel();
		JLabel sourceLabel = new JLabel();
		JLabel targetLabel = new JLabel();
		language.add(spaceLabel, BorderLayout.NORTH);
		language.add(sourceLabel, BorderLayout.WEST);
		language.add(targetLabel, BorderLayout.EAST);
		language.add(space2Label, BorderLayout.SOUTH);
		spaceLabel.setText(" ");
		space2Label.setText(" ");
		sourceLabel.setText("Source Language: " + sourceCombo.getSelectedItem());
		targetLabel.setText("Target Language: " + targetCombo.getSelectedItem());
		
		JScrollPane candidateTemplatesScrollPane = new JScrollPane(tree);
		candidateTemplatesTab.add(candidateTemplatesScrollPane, BorderLayout.CENTER);
		
		return candidateTemplatesTab;
	}

	private String startTranslation() {
		String strInput = getSourceText(), 
			strSourceLanguage = getSourceLanguage(), 
			strTargetLanguage = getTargetLanguage();
			
		char cSourceLanguage = Character.toLowerCase(strSourceLanguage.charAt(0));
		char cTargetLanguage = Character.toLowerCase(strTargetLanguage.charAt(0));
		boolean bEnglishSource;
		int nSentenceNo = 0;
		long lTotalIATime = 0;
		long lTotalTranslationTime = 0;
		
		if(cSourceLanguage == 'e') {
			bEnglishSource = true;
		}else {
			bEnglishSource = false;
		}
		
		//InputAnalysis
		InputAnalyzer ia = new InputAnalyzer();
		
		lTotalIATime = System.currentTimeMillis();
		Vector vSentences = ia.analyzeTranslateInput(strInput, cTargetLanguage, "Regular Expression");
		lTotalIATime = System.currentTimeMillis() - lTotalIATime;

		//Translating
		String strTranslation = null;
		
		if(vSentences != null) {
			nSentenceNo = vSentences.size();
			Translator translator = new Translator(bEnglishSource);
			lTotalTranslationTime = System.currentTimeMillis();
			strTranslation = translator.translate(vSentences);
			lTotalTranslationTime = System.currentTimeMillis() - lTotalTranslationTime;

			translateTree = translator.getTree();
			
			vOrigSentences = vSentences;
			vTranslatedSentences = translator.getSentences();
		
//			GUI.clearStatus();
			GUI.appendToStatus("Translation Completed.");
			
			if (bEnglishSource) GUI.appendToStatus("\nEnglish to Filipino");
			else GUI.appendToStatus("Filipino to English");
			GUI.appendToStatus("Number of Sentences: " + nSentenceNo);
			GUI.appendToStatus("Total IA Time: " + lTotalIATime + " ms");
			GUI.appendToStatus("Total Translation Time: " + lTotalTranslationTime + " ms");
			GUI.appendToStatus("Total IA & Translation Time: " + (lTotalIATime + lTotalTranslationTime) + " ms");
		}else {
			//error message here!!!
			vOrigSentences = null;
			vTranslatedSentences = null;

//			GUI.clearStatus();
			GUI.appendToStatus("Translation Completed.");
		}
		
		return strTranslation;
	}

	//tab
	public JTabbedPane getTabbedPane() {
		return tabbedPane;
	}
	
	//mode	
	public char getMode() {
		return tabMode;
	}

	public void setMode(char mode) {
		tabMode = mode;
	}

	//Text Area
	public JTextArea getSourceTextArea(){
		return sourceTextArea;
	}

	public JTextArea getTranslatedTextArea(){
		return translatedTextArea;
	}

	//Text
	public void setSourceText(String s){
		sourceTextArea.setText(s);
	}

	public void setTranslatedText(String s) {
		translatedTextArea.setText(s);
	}

	public String getSourceText() {
		return sourceTextArea.getText();
	}

	public String getTranslatedText() {
		return translatedTextArea.getText();
	}

	//Language
	public String getSourceLanguage(){
		return (String) sourceCombo.getModel().getSelectedItem();
	}

	public String getTargetLanguage(){
		return (String) targetCombo.getModel().getSelectedItem();
	}

	class TabAction implements ChangeListener {
		TranslationModeViewer translationModeViewer;
		
		public TabAction(TranslationModeViewer translationModeViewer) {
			this.translationModeViewer = translationModeViewer;
		}
	
		public void stateChanged(ChangeEvent e) {
			if(translationModeViewer.getTabbedPane().getSelectedIndex() == 0) {
				translationModeViewer.setMode('S');
			}else if(translationModeViewer.getTabbedPane().getSelectedIndex() == 1) {
				translationModeViewer.setMode('T');
			}else {
				translationModeViewer.setMode('\0');
			}
		}		
	}

	class ChangeAction implements DocumentListener {
		JTextArea tArea;
		
		public ChangeAction(JTextArea tArea) {
			this.tArea = tArea;
		}
	
		private void changeTitle() {
			if(!((TitledBorder)tArea.getBorder()).getTitle().endsWith("*")) {
				tArea.setBorder(new TitledBorder(((TitledBorder)tArea.getBorder()).getTitle() + "*"));
			}
		}		

		public void changedUpdate(DocumentEvent e) {
			changeTitle();
		}

		public void removeUpdate(DocumentEvent e){
			changeTitle();
		}
		
		public void insertUpdate(DocumentEvent e){
			changeTitle();
		}
	}
}